﻿using K9Nano.Dependency;
using K9Nano.Enums;
using K9Nano.Exceptions;
using K9Nano.Serialization;
using K9Nano.Session;

namespace K9Nano.Settings;

public class SettingManager(ISettingStore settingStore,
    IUserContextAccessor userContextAccessor,
    ISettingDefinitionManager settingDefinitionManager) : ISettingManager, IScopedDependency
{
    protected readonly ISettingStore SettingStore = settingStore;
    protected readonly IUserContextAccessor UserContextAccessor = userContextAccessor;
    protected readonly ISettingDefinitionManager SettingDefinitionManager = settingDefinitionManager;

    protected long? CurrentUserId => UserContextAccessor.CurrentUser?.UserId;

    public virtual Task<string?> GetSettingValueAsync(string name, CancellationToken cancellation = default)
    {
        return GetSettingValueAsync(name, CurrentUserId, cancellation);
    }

    public virtual async Task<string?> GetSettingValueAsync(string name, long? userId, CancellationToken cancellation = default)
    {
        if (!SettingDefinitionManager.TryGetSettingDefinition(name, out var settingDefinition))
        {
            throw new FriendlyException($"尚未定义名称为{name}的设置");
        }

        var scopedUserId = settingDefinition!.Scope == ESettingScope.User ? userId : default;
        var setting = await SettingStore.GetSettingOrNullAsync(scopedUserId, name, cancellation);
        if (setting == null)
        {
            return settingDefinition!.DefaultValue;
        }

        return setting.Value;
    }

    public virtual Task ChangeSettingAsync(string name, string value, CancellationToken cancellation = default)
    {
        return ChangeSettingAsync(name, value, CurrentUserId, cancellation);
    }

    public virtual async Task ChangeSettingAsync(string name, string value, long? userId, CancellationToken cancellation = default)
    {
        if (!SettingDefinitionManager.TryGetSettingDefinition(name, out var settingDefinition))
        {
            throw new FriendlyException($"尚未定义名称为{name}的设置");
        }

        var scopedUserId = settingDefinition!.Scope == ESettingScope.User ? userId : default;

        var currentValue = new SettingInfo(scopedUserId, name, value);

        await SettingStore.CreateOrUpdateAsync(currentValue, cancellation);

        AfterSettingChanged(currentValue);
    }

    protected virtual void AfterSettingChanged(SettingInfo currentValue)
    {
    }

    public virtual async Task ChangeSettingJsonAsync(string name, object value, long? userId, CancellationToken cancellation = default)
    {
        var json = JsonHelper.Serialize(value);
        await ChangeSettingAsync(name, json, userId, cancellation);
    }

    public virtual async Task ChangeSettingJsonAsync(string name, object value, CancellationToken cancellation = default)
    {
        await ChangeSettingJsonAsync(name, value, CurrentUserId, cancellation);
    }

    public virtual async Task<T?> GetJsonAsync<T>(string name, CancellationToken cancellation = default)
    {
        var json = await GetSettingValueAsync(name, cancellation);
        if (string.IsNullOrEmpty(json)) return default;
        var result = JsonHelper.Deserialize<T>(json);
        return result;
    }

    public virtual async Task<T?> GetJsonAsync<T>(string name, long? userId, CancellationToken cancellation = default)
    {
        var json = await GetSettingValueAsync(name, userId, cancellation);
        if (string.IsNullOrEmpty(json)) return default;
        var result = JsonHelper.Deserialize<T>(json);
        return result;
    }
}
